//////////////////////////////////////////////////////////////////////
// ParticleSystem.h
//
// SHEN Fangyang
// me@shenfy.com
//
// Copyright (C) SHEN Fangyang, 2011, All rights reserved.
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//  Brief Description
//
//	CPU managed particle system
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include <BasisObj.h>
#include <list>
#include <boost/function.hpp>
#include <vector>
#include <boost/scoped_array.hpp>
#include <boost/weak_ptr.hpp>

namespace grflib
{
	namespace engine
	{
		namespace aux
		{
            //////////////////////////////////////////
            // CPU managed particle system
            template<typename TParticle>
            class CParticleSystem : public grflib::engine::core::IRenderable
            {
            public:
                CParticleSystem(std::size_t maxParticleNum);
                ~CParticleSystem(void);
                explicit CParticleSystem(void);

                //technique and material
                void SetEffectTechnique(char *effectName, char *techniqueName)
                { m_effectName = effectName; m_techniqueName = techniqueName; }

                void SetMaterialName(char *materialName)
                { m_materialName = materialName; }

                //particles
                void AddParticle(const TParticle &particle);
                //bool AddParticles(const std::vector<TParticle> &particles);

                //life cycle
                virtual HRESULT OnCreateDevice(ID3D10Device *pd3dDevice,
                                               const DXGI_SURFACE_DESC *pBufferSurfaceDesc);
                virtual HRESULT OnResize(ID3D10Device *pd3dDevice, 
                                         IDXGISwapChain *pSwapChain,
                                         const DXGI_SURFACE_DESC *pBufferSurfaceDesc)
                { return S_OK; }

                virtual void FrameMove(double fTime, float fElapsedTime);
                virtual HRESULT PreRender(ID3D10Device *pd3dDevice,
                                         const D3DXMATRIX *pWorldMat,
                                         double fTime,
                                         float fElapsedTime,
                                         UINT pass);
                virtual HRESULT Render(ID3D10Device *pd3dDevice,
                                         const D3DXMATRIX *pWorldMat,
                                         double fTime,
                                         float fElapsedTime,
                                         UINT pass);
                virtual void OnDestroy(void);

                //member access
                virtual grflib::engine::core::BBox<float> &GetBoundingBox(void);
                void ResetMaximumParticleNum(std::size_t maxNum);

                //typedefs
                typedef std::list<TParticle, boost::pool_allocator<TParticle>> particle_list_type;

            protected:
                HRESULT CreateVertexBuffer(ID3D10Device *pd3dDevice);
                void DestroyVertexBuffer(void);

            protected:
                particle_list_type m_particles;
                boost::scoped_array<typename TParticle::vertex_type> m_particleVertices;
                boost::scoped_array<DWORD> m_particleIndices;
                ID3D10Buffer *m_pVertexBuffer;
                ID3D10Buffer *m_pIndexBuffer;
                std::size_t m_maxParticleNum;
                grflib::engine::core::BBox<float> m_bbox;
                std::string m_effectName;
                std::string m_techniqueName;
                std::string m_materialName;
                std::size_t m_population;

            protected:
                //pass between PreRender and Render
                D3D10_TECHNIQUE_DESC m_techDesc;
                ID3D10EffectTechnique *m_pTech;
                boost::weak_ptr<grflib::engine::core::CEffect> m_pEffect;
            };
            //////////////////////////////////////////

		} //namespace aux
	} //namespace engine
} //namespace grflib


#include <ParticleSystemImpl.hpp>